﻿using Black.Minecraft.Editor.Models;
using Black.Minecraft.Editor.ViewModels.Core;
using Black.Minecraft.Editor.ViewModels.DataModels;
using Black.NBT;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;

namespace Black.Minecraft.Editor.ViewModels
{
    /// <summary>
    /// ViewModel statique pour la gestion des données
    /// </summary>
    public class MainViewModel : BaseViewModel
    {
        #region Constantes

        private static readonly string LOCAL_SAVE_PATH = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\.minecraft\\saves";

        #endregion

        #region Singleton

        public static readonly MainViewModel Instance = new MainViewModel();

        #endregion

        #region Propriétés

        /// <summary>
        /// Obtient la liste pour les choix Yes / No
        /// </summary>
        public List<ByteBinaryChoiceType> ByteBinaryChoices
        {
            get
            {
                return (this._byteBinaryChoices);
            }
        }

        /// <summary>
        /// Obtient la commande de réinitialisation de la recherche
        /// </summary>
        public ICommand ClearSearchCommand
        {
            get
            {
                return (this._clearSearchCommand);
            }
        }

        /// <summary>
        /// Obtient la liste des définitions des enchantements
        /// </summary>
        public ReadOnlyCollection<EnchantDefDataModel> EnchantsDefinition
        {
            get
            {
                return (this._enchantsDefinition);
            }
            set
            {
                if (this._enchantsDefinition != value)
                {
                    this._enchantsDefinition = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient la liste des définitions source des enchantements
        /// </summary>
        public List<EnchantDefDataModel> EnchantsDefinitionSource
        {
            get
            {
                return (this._enchantsDefinitionSource);
            }
            set
            {
                if (this._enchantsDefinitionSource != value)
                {
                    this._enchantsDefinitionSource = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit les informations de la partie
        /// </summary>
        public GameInformationViewModel GameInformation
        {
            get
            {
                return (this._gameInformation);
            }
            set
            {
                if (this._gameInformation != value)
                {
                    this._gameInformation = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit l'inventaire
        /// </summary>
        public InventoryDataModel Inventory
        {
            get
            {
                return (this._inventory);
            }
            set
            {
                if (this._inventory != value)
                {
                    this._inventory = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit si le menu Close est actif
        /// </summary>
        public bool IsMenuCloseEnable
        {
            get
            {
                return (this._menuCloseEnable);
            }
            set
            {
                if (this._menuCloseEnable != value)
                {
                    this._menuCloseEnable = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit si le menu Open Save est actif
        /// </summary>
        public bool IsMenuOpenSaveEnable
        {
            get
            {
                return (this._menuOpenSaveEnable);
            }
            set
            {
                if (this._menuOpenSaveEnable != value)
                {
                    this._menuOpenSaveEnable = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit si le menu Save est actif
        /// </summary>
        public bool IsMenuSaveEnable
        {
            get
            {
                return (this._menuSaveEnable);
            }
            set
            {
                if (this._menuSaveEnable != value)
                {
                    this._menuSaveEnable = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit si le menu SaveAs est actif
        /// </summary>
        public bool IsMenuSaveAsEnable
        {
            get
            {
                return (this._menuSaveAsEnable);
            }
            set
            {
                if (this._menuSaveAsEnable != value)
                {
                    this._menuSaveAsEnable = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit si on a modifier un élement
        /// </summary>
        public bool IsModified
        {
            get
            {
                return (this._isModified);
            }
            set
            {
                if (this._isModified != value)
                {
                    this._isModified = value;
                    this.OnPropertyChanged();
                }

                this.RefreshTitle();
            }
        }

        /// <summary>
        /// Obtient ou définit si un fichier est ouvert
        /// </summary>
        public bool IsOpen
        {
            get
            {
                return (this._isOpen);
            }
            set
            {
                if (this._isOpen != value)
                {
                    this._isOpen = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit si le fichier ouvert vient d'un serveur
        /// </summary>
        public bool IsServerGame
        {
            get
            {
                return (this._isServerGame);
            }
            set
            {
                if (this._isServerGame != value)
                {
                    this._isServerGame = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient la liste des définitions des objets
        /// </summary>
        public ReadOnlyCollection<ItemDataModel> ItemsDefinition
        {
            get
            {
                return (this._itemsDefinition);
            }
            set
            {
                if (this._itemsDefinition != value)
                {
                    this._itemsDefinition = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient la liste des définitions source des objets
        /// </summary>
        public List<ItemDataModel> ItemsDefinitionSource
        {
            get
            {
                return (this._itemsDefinitionSource);
            }
            set
            {
                if (this._itemsDefinitionSource != value)
                {
                    this._itemsDefinitionSource = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient la commande du menu About
        /// </summary>
        public ICommand MenuAboutCommand
        {
            get
            {
                return (this._menuAboutCommand);
            }
        }

        /// <summary>
        /// Obtient la commande du menu Close
        /// </summary>
        public ICommand MenuCloseCommand
        {
            get
            {
                return (this._menuCloseCommand);
            }
        }

        /// <summary>
        /// Obtient la commande du menu Exit
        /// </summary>
        public ICommand MenuExitCommand
        {
            get
            {
                return (this._menuExitCommand);
            }
        }

        /// <summary>
        /// Obtient la commande du menu Open
        /// </summary>
        public ICommand MenuOpenCommand
        {
            get
            {
                return (this._menuOpenCommand);
            }
        }

        /// <summary>
        /// Obtient ou défint la commande pour l'ouverture d'une sauvegarde locale
        /// </summary>
        public ICommand MenuOpenSaveCommand
        {
            get
            {
                return (this._menuOpenSaveCommand);
            }
        }

        /// <summary>
        /// Obtient la commande pour le menu options
        /// </summary>
        public ICommand MenuOptionsCommand
        {
            get
            {
                return (this._menuOptionsCommand);
            }
        }

        /// <summary>
        /// Obtient la commande du menu Save
        /// </summary>
        public ICommand MenuSaveCommand
        {
            get
            {
                return (this._menuSaveCommand);
            }
        }

        /// <summary>
        /// Obtient la commande du menu SaveAs
        /// </summary>
        public ICommand MenuSaveAsCommand
        {
            get
            {
                return (this._menuSaveAsCommand);
            }
        }

        /// <summary>
        /// Obtient ou définit les sauvegardes locales
        /// </summary>
        public ObservableCollection<LocalSaveDataModel> MinecraftLocalSaves
        {
            get
            {
                return (this._minecraftLocalSaves);
            }
        }

        /// <summary>
        /// Obtient les options de l'application
        /// </summary>
        public OptionsDataModel Options
        {
            get
            {
                return (this._options);
            }
        }

        /// <summary>
        /// Obtient ou définit les informations du joueur
        /// </summary>
        public PlayerInformationDataModel PlayerInformation
        {
            get
            {
                return (this._playerInformation);
            }
            set
            {
                if (this._playerInformation != value)
                {
                    this._playerInformation = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit la popup a afficher
        /// </summary>
        public BaseViewModel Popup
        {
            get
            {
                return (this._popup);
            }
            set
            {
                if (this._popup != value)
                {
                    this._popup = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient la commande de fermeture de la popup
        /// </summary>
        public ICommand PopupCloseCommand
        {
            get
            {
                return (this._popupCloseCommand);
            }
        }

        /// <summary>
        /// Obtient ou définit le state pour la popup
        /// </summary>
        public string PopupState
        {
            get
            {
                return (this._popupState);
            }
            set
            {
                if (this._popupState != value)
                {
                    this._popupState = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient la command de changement de texte sur la recherche
        /// </summary>
        public ICommand SearchChangedCommand
        {
            get
            {
                return (this._searchChangedCommand);
            }
        }

        /// <summary>
        /// Obtient ou définit la liste des servers
        /// </summary>
        public ObservableCollection<ServerDefinitionDataModel> ServerDefinitions
        {
            get
            {
                return (this._serverDefinitions);
            }
            set
            {
                if (this._serverDefinitions != value)
                {
                    this._serverDefinitions = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Obtient la liste des types de partie en solo
        /// </summary>
        public List<SoloGameType> SoloGameTypes
        {
            get
            {
                return (this._soloGameTypes);
            }
        }

        /// <summary>
        /// Obtient ou définit si le titre
        /// </summary>
        public string Title
        {
            get
            {
                return (this._title);
            }
            set
            {
                if (this._title != value)
                {
                    this._title = value;
                    this.OnPropertyChanged();
                }
            }
        }

        #endregion

        #region Variables d'instances

        private bool _isModified;
        private bool _menuCloseEnable;
        private bool _menuOpenSaveEnable;
        private bool _menuSaveEnable;
        private bool _menuSaveAsEnable;
        private bool _isOpen;
        private bool _isServerGame;
        private string _title;
        private string _search;
        private string _popupState;
        private NBTFile _currentFile;
        private BaseViewModel _popup;
        private OptionsDataModel _options;
        private InventoryDataModel _inventory;
        private PlayerInformationDataModel _playerInformation;
        private GameInformationViewModel _gameInformation;
        private List<ItemDataModel> _itemsDefinitionSource;
        private List<EnchantDefDataModel> _enchantsDefinitionSource;
        private ReadOnlyCollection<ItemDataModel> _itemsDefinition;
        private ReadOnlyCollection<EnchantDefDataModel> _enchantsDefinition;
        private ObservableCollection<LocalSaveDataModel> _minecraftLocalSaves;
        private List<SoloGameType> _soloGameTypes;
        private List<ByteBinaryChoiceType> _byteBinaryChoices;
        private ObservableCollection<ServerDefinitionDataModel> _serverDefinitions;

        private RelayCommand _menuAboutCommand;
        private RelayCommand _menuCloseCommand;
        private RelayCommand _menuExitCommand;
        private RelayCommand _menuOpenCommand;
        private RelayCommand _menuSaveCommand;
        private RelayCommand _menuSaveAsCommand;
        private RelayCommand _menuOpenSaveCommand;
        private RelayCommand _menuOptionsCommand;
        private RelayCommand _clearSearchCommand;
        private RelayCommand _searchChangedCommand;
        private RelayCommand _popupCloseCommand;

        #endregion

        #region Constructeurs

        /// <summary>
        /// Constructeur de la classe
        /// </summary>
        public MainViewModel()
            : base()
        {
            // Initialisation

            this._isOpen = false;
            this._isServerGame = false;
            this._isModified = false;
            this._menuCloseEnable = false;
            this._menuSaveAsEnable = false;
            this._menuSaveEnable = false;
            this._menuOpenSaveEnable = false;
            this._popupState = "Normal";

            // Chargement des données

            this._options = new OptionsDataModel(Models.Options.GetOptions());

            this.LoadItems();
            this.LoadEnchants();
            this.LoadLocalSaves();
            this.LoadServers();
            this.RefreshTitle();

            // Chargement des type de parties

            this._soloGameTypes = new List<SoloGameType>();
            this._soloGameTypes.Add(SoloGameType.Survival);
            this._soloGameTypes.Add(SoloGameType.Creative);

            // Chargement pour AllowCommand

            this._byteBinaryChoices = new List<ByteBinaryChoiceType>();
            this._byteBinaryChoices.Add(ByteBinaryChoiceType.No);
            this._byteBinaryChoices.Add(ByteBinaryChoiceType.Yes);
        }

        #endregion

        #region Fonctions publiques

        /// <summary>
        /// Affiche une popup à partir d'un ViewModel
        /// </summary>
        /// <param name="viewModel">Instance du ViewModel a afficher</param>
        public void ClosePopup()
        {
            this.PopupState = "Normal";
        }

        /// <summary>
        /// Sauvegarde la liste des serveurs
        /// </summary>
        public void SaveServers()
        {
            List<ServerDefinition> list = new List<ServerDefinition>();

            foreach (ServerDefinitionDataModel item in this._serverDefinitions)
                list.Add(item.GetData());

            ServerDefinition.SetServerList(list);
        }

        /// <summary>
        /// Affiche une popup à partir d'un ViewModel
        /// </summary>
        /// <param name="viewModel">Instance du ViewModel a afficher</param>
        public void ShowPopup(BaseViewModel viewModel)
        {
            this.Popup = viewModel;
            this.PopupState = "Opened";
        }

        #endregion

        #region Fonctions protégées

        /// <summary>
        /// Initialise les commandes
        /// </summary>
        protected override void OnInitializeCommand()
        {
            this._menuAboutCommand = new RelayCommand(this.OnMenuAboutCommandExecute);
            this._menuCloseCommand = new RelayCommand(this.OnMenuCloseCommandExecute);
            this._menuOpenSaveCommand = new RelayCommand(this.OnMenuOpenSaveCommandExecute);
            this._menuExitCommand = new RelayCommand(this.OnMenuExitCommandExecute);
            this._menuOpenCommand = new RelayCommand(this.OnMenuOpenCommandExecute);
            this._menuSaveAsCommand = new RelayCommand(this.OnMenuSaveAsCommandExecute);
            this._menuSaveCommand = new RelayCommand(this.OnMenuSaveCommandExecute);
            this._clearSearchCommand = new RelayCommand(this.OnClearSearchCommandExecute);
            this._searchChangedCommand = new RelayCommand(this.OnSearchChangedCommandExecute);
            this._popupCloseCommand = new RelayCommand(this.OnPopupCloseCommandExecute);
            this._menuOptionsCommand = new RelayCommand(this.OnMenuOptionsCommandExecute);
        }

        /// <summary>
        /// Se produit sur la fin du chargement de l'application
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        protected override void OnLoadedCommandExecute(object parameter)
        {
            if (this._options.LoadLastFile && !string.IsNullOrWhiteSpace(this._options.LastFile) && File.Exists(this._options.LastFile))
                this.OpenFile(this._options.LastFile);
        }

        #endregion

        #region Fonctions privées

        /// <summary>
        /// Fait une copie de sauvegarde du fichier
        /// </summary>
        /// <param name="filename">Fichier a backuper</param>
        private void BackupFile(string filename)
        {
            // Extraction des informations

            string path = Path.GetDirectoryName(filename);
            string file = Path.GetFileNameWithoutExtension(filename);
            string extension = Path.GetExtension(filename);

            // Vérificaiton existance répertoire de sauvegarde

            if (!Directory.Exists(path + "\\EditorBackups"))
                Directory.CreateDirectory(path + "\\EditorBackups");

            // Création de la sauvegarde

            File.Copy(filename, path + "\\EditorBackups\\" + file + "_" + DateTime.Now.ToString("ddMMyyyy_HHmmss") + extension);
        }

        /// <summary>
        /// Ferme le fichier en cour
        /// </summary>
        private void CloseFile()
        {
            // Fermeture

            this.GameInformation = null;
            this.PlayerInformation = null;
            this.Inventory = null;

            this._currentFile = null;

            this.IsMenuCloseEnable = false;
            this.IsMenuSaveAsEnable = false;
            this.IsMenuSaveEnable = false;

            this.IsOpen = false;
            this.IsModified = false;
            this.IsServerGame = false;

            this.RefreshTitle();
        }

        /// <summary>
        /// Effectue la recherche
        /// </summary>
        private void ExecuteSearch()
        {
            // On effectue la recherche

            var result = from p in this._itemsDefinitionSource
                         where p.Name.ToLower().Contains(this._search.ToLower())
                         select p;

            // On transfert les éléments

            this.ItemsDefinition = new ReadOnlyCollection<ItemDataModel>(result.ToList());
        }

        /// <summary>
        /// Charge les données de l'inventaire
        /// </summary>
        private void LoadDataInformation()
        {
            // Récupération des informations de la partie

            TagCompound game = (TagCompound)(from p in this._currentFile.Root.Items
                                             where p.Name == "Data"
                                             && p.TagType == TagType.Compound
                                             && ((TagCompound)p)["Player"] != null
                                             select p).FirstOrDefault();

            if (game != null)
                this.GameInformation = new GameInformationViewModel(game);
            else
                this.IsServerGame = true;

            // Récupération du joueur

            if (game == null)
                this.PlayerInformation = new PlayerInformationDataModel(this._currentFile.Root);
            else
                this.PlayerInformation = new PlayerInformationDataModel(game["Player"] as TagCompound);

            // Récupération de l'inventaire

            this.Inventory = new InventoryDataModel(this.PlayerInformation.GetData()["Inventory"] as TagList);
        }

        /// <summary>
        /// Charge la liste des objets
        /// </summary>
        private void LoadEnchants()
        {
            List<Enchant> list = Enchant.LoadEnchants();
            this._enchantsDefinitionSource = new List<EnchantDefDataModel>();

            foreach (Enchant data in list)
                this._enchantsDefinitionSource.Add(new EnchantDefDataModel(data));

            this.EnchantsDefinition = new ReadOnlyCollection<EnchantDefDataModel>(this._enchantsDefinitionSource);
        }

        /// <summary>
        /// Charge la liste des objets
        /// </summary>
        private void LoadItems()
        {
            List<Item> list = Item.LoadItems();
            this._itemsDefinitionSource = new List<ItemDataModel>();

            foreach (Item data in list)
                this._itemsDefinitionSource.Add(new ItemDataModel(data));

            this.ItemsDefinition = new ReadOnlyCollection<ItemDataModel>(this._itemsDefinitionSource);
        }

        /// <summary>
        /// Charge la définition des sauvegardes locales
        /// </summary>
        private void LoadLocalSaves()
        {
            this._menuOpenSaveEnable = false;
            this._minecraftLocalSaves = new ObservableCollection<LocalSaveDataModel>();

            // Vérification existance répertoire

            if (!Directory.Exists(MainViewModel.LOCAL_SAVE_PATH))
                return;

            // Récupération des sauvegardes

            string[] result = Directory.GetDirectories(MainViewModel.LOCAL_SAVE_PATH);

            foreach (string savePath in result)
            {
                // Vérification existance sauvegarde

                if (File.Exists(savePath + "\\level.dat"))
                {
                    string[] split = savePath.Split('\\');
                    this._minecraftLocalSaves.Add(new LocalSaveDataModel(split[split.Length - 1], savePath + "\\level.dat"));
                }
            }

            // Remise à jour de l'indicateur

            this._menuOpenSaveEnable = this._minecraftLocalSaves.Count > 0;
        }

        /// <summary>
        /// Charge la liste des serveurs
        /// </summary>
        private void LoadServers()
        {
            ObservableCollection<ServerDefinitionDataModel> list = new ObservableCollection<ServerDefinitionDataModel>();

            foreach (ServerDefinition def in ServerDefinition.GetServerList())
                list.Add(new ServerDefinitionDataModel(def));

            this.ServerDefinitions = list;
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu ClearSearch
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnClearSearchCommandExecute(object parameter)
        {
            this._search = string.Empty;
            this.ExecuteSearch();
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu About
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuAboutCommandExecute(object parameter)
        {
            this.ShowPopup(new AboutViewModel());
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu Close
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuCloseCommandExecute(object parameter)
        {
            // Vérification enregistrement en cour

            if (!this.VerifyPendingChange())
                return;

            // Fermeture du fichier

            this.CloseFile();
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu Exit
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuExitCommandExecute(object parameter)
        {
            Application.Current.Shutdown();
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu Open
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuOpenCommandExecute(object parameter)
        {
            // Vérification enregistrement en cour

            if (!this.VerifyPendingChange())
                return;

            // Ouverture de la dialog

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.DefaultExt = ".dat";
            dlg.AddExtension = true;
            dlg.FilterIndex = 0;
            dlg.Filter = "NBT Data file (.dat)|*.dat|All files (*)|*.*";

            if (this._currentFile != null)
                dlg.FileName = this._currentFile.Filename;

            Nullable<bool> result = dlg.ShowDialog();

            if (!result.HasValue || !result.Value)
                return;

            // Ouverture du fichier

            this.OpenFile(dlg.FileName);
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu Open
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuOpenSaveCommandExecute(object parameter)
        {
            // Vérification enregistrement en cour

            if (!this.VerifyPendingChange())
                return;

            // Ouverture fichier

            LocalSaveDataModel item = parameter as LocalSaveDataModel;

            if (item == null)
                return;

            this.OpenFile(item.Filename);
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu options
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuOptionsCommandExecute(object parameter)
        {
            this.ShowPopup(new OptionsViewModel());
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu Save
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuSaveCommandExecute(object parameter)
        {
            if (this._currentFile != null && this.Save(this._currentFile.Filename))
                this.Title = string.Format("");

            this._isModified = false;
            this.RefreshTitle();
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu SaveAs
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnMenuSaveAsCommandExecute(object parameter)
        {
            // Vérification existance fichier

            if (this._currentFile == null)
                return;

            // Récupération du nomdde fichier

            SaveFileDialog dlg = new SaveFileDialog();
            dlg.FileName = this._currentFile.Filename;
            dlg.DefaultExt = ".dat";
            dlg.AddExtension = true;
            dlg.FilterIndex = 0;
            dlg.Filter = "NBT Data file (.dat)|*.dat|All files (*)|*.*";

            Nullable<bool> result = dlg.ShowDialog();

            if (!result.HasValue || !result.Value)
                return;

            // Sauvegarde

            this._currentFile.Filename = dlg.FileName;

            if (this.Save(this._currentFile.Filename))
                this.Title = string.Format("");

            this._isModified = false;
            this.RefreshTitle();
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande de fermeture de la popup
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnPopupCloseCommandExecute(object parameter)
        {
            this.ClosePopup();
        }

        /// <summary>
        /// Se produit sur l'éxécution de la commande du menu SearchChanged
        /// </summary>
        /// <param name="parameter">Paramètre de la commande</param>
        private void OnSearchChangedCommandExecute(object parameter)
        {
            this._search = (string)parameter;
            this.ExecuteSearch();
        }

        /// <summary>
        /// Ouvre un fichier
        /// </summary>
        /// <param name="filename">Chemin du fichier</param>
        private void OpenFile(string filename)
        {
            // Ouverture du fichier

            try
            {
                // On ferme tout

                this.CloseFile();

                // On tente l'ouverture

                this._currentFile = NBTFile.OpenFile(filename);

                // On charge les données

                this.LoadDataInformation();

                // Sauvegarde des settings

                this._options.LastFile = filename;
                this._options.Save();
            }
            catch (Exception ex)
            {
                this.CloseFile();
                MessageBox.Show(string.Format("An error occured :\n\n{0}", ex.Message), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            // On rafraichis le titre

            this.IsMenuCloseEnable = true;
            this.IsMenuSaveAsEnable = true;
            this.IsMenuSaveEnable = true;

            this.RefreshTitle();
            this.IsOpen = true;
        }

        /// <summary>
        /// Rafraichis le titre de l'application
        /// </summary>
        private void RefreshTitle()
        {
            string title = "Black - Minecraft Editor ";

            if (this._currentFile != null)
            {
                title += "[";

                if (this._isModified)
                    title += "*";

                title += this._currentFile.Filename + "]";
            }

            this.Title = title;
        }

        /// <summary>
        /// Sauvegarde le fichier a l'endroit indiqué
        /// </summary>
        /// <param name="filename">Chemin du fichier</param>
        /// <returns>TRUE sauvegarde réussie, FALSE sinon</returns>
        private bool Save(string filename)
        {
            try
            {
                // Gestion des backups

                if (this._options.BackupFile)
                    this.BackupFile(filename);

                // Sauvegarde

                this._currentFile.SaveAs(filename);

                // Terminée avec succès

                return (true);
            }
            catch (Exception e)
            {
                MessageBox.Show(string.Format("An error occured :\n\n{0}", e.Message), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return (false);
            }
        }

        /// <summary>
        /// Vérifie si des données sont en cours de modification
        /// </summary>
        /// <returns></returns>
        private bool VerifyPendingChange()
        {
            // On verifie si un fichier existe avec modication

            if (this._currentFile == null || !this._isModified)
                return (true);

            // Affichage du message

            MessageBoxResult result = MessageBox.Show("You have made ​​changes on this file, do you want to save ?", "Modification in progress", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);

            // Traitement résultat

            if (result == MessageBoxResult.Cancel)
                return (false);

            if (result == MessageBoxResult.Yes && !this.Save(this._currentFile.Filename))
                return (false);

            // Terminée

            return (true);
        }

        #endregion
    }
}
